home *** CD-ROM | disk | FTP | other *** search
/ Freelog 125 / Freelog_MarsAvril2015_No125.iso / Musique / Quod Libet / quodlibet-3.3.0-portable.exe / quodlibet-3.3.0-portable / data / bin / quodlibet / qltk / tagsfrompath.pyc (.txt) < prev    next >
Python Compiled Bytecode  |  2014-12-31  |  12KB  |  312 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.7)
  3.  
  4. import re
  5. from gi.repository import Gtk
  6. from quodlibet import config
  7. from quodlibet import const
  8. from quodlibet import qltk
  9. from quodlibet import util
  10. from quodlibet.plugins import PluginManager
  11. from quodlibet.qltk._editutils import FilterPluginBox, FilterCheckButton
  12. from quodlibet.qltk._editutils import EditingPluginHandler, OverwriteWarning
  13. from quodlibet.qltk._editutils import WriteFailedError
  14. from quodlibet.qltk.wlw import WritingWindow
  15. from quodlibet.qltk.views import TreeViewColumn
  16. from quodlibet.qltk.cbes import ComboBoxEntrySave
  17. from quodlibet.qltk.models import ObjectStore
  18. from quodlibet.util.path import fsdecode
  19. from quodlibet.util.tagsfrompath import TagsFromPattern
  20. from quodlibet.util.string.splitters import split_value
  21. from quodlibet.util import connect_obj
  22.  
  23. class UnderscoresToSpaces(FilterCheckButton):
  24.     _label = _('Replace _underscores with spaces')
  25.     _section = 'tagsfrompath'
  26.     _key = 'underscores'
  27.     _order = 1
  28.     
  29.     def filter(self, tag, value):
  30.         return value.replace('_', ' ')
  31.  
  32.  
  33.  
  34. class TitleCase(FilterCheckButton):
  35.     _label = _('_Title-case tags')
  36.     _section = 'tagsfrompath'
  37.     _key = 'titlecase'
  38.     _order = 1.1
  39.     
  40.     def filter(self, tag, value):
  41.         return util.title(value)
  42.  
  43.  
  44.  
  45. class SplitTag(FilterCheckButton):
  46.     _label = _('Split into multiple _values')
  47.     _section = 'tagsfrompath'
  48.     _key = 'split'
  49.     _order = 1.2
  50.     
  51.     def filter(self, tag, value):
  52.         spls = config.get('editing', 'split_on').decode('utf-8', 'replace')
  53.         spls = spls.split()
  54.         return '\n'.join(split_value(value, spls))
  55.  
  56.  
  57.  
  58. class TagsFromPathPluginHandler(EditingPluginHandler):
  59.     from quodlibet.plugins.editing import TagsFromPathPlugin
  60.     Kind = TagsFromPathPlugin
  61.  
  62.  
  63. class ListEntry(object):
  64.     
  65.     def __init__(self, song):
  66.         self.song = song
  67.         self.matches = { }
  68.  
  69.     
  70.     def get_match(self, key):
  71.         return self.matches.get(key, u'')
  72.  
  73.     
  74.     def replace_match(self, key, value):
  75.         self.matches[key] = value
  76.  
  77.     
  78.     def name(self):
  79.         return fsdecode(self.song('~basename'))
  80.  
  81.     name = property(name)
  82.  
  83.  
  84. class TagsFromPath(Gtk.VBox):
  85.     title = _('Tags From Path')
  86.     FILTERS = [
  87.         UnderscoresToSpaces,
  88.         TitleCase,
  89.         SplitTag]
  90.     handler = TagsFromPathPluginHandler()
  91.     
  92.     def init_plugins(cls):
  93.         PluginManager.instance.register_handler(cls.handler)
  94.  
  95.     init_plugins = classmethod(init_plugins)
  96.     
  97.     def __init__(self, parent, library):
  98.         super(TagsFromPath, self).__init__(spacing = 6)
  99.         self.set_border_width(12)
  100.         hbox = Gtk.HBox(spacing = 6)
  101.         cbes_defaults = const.TBP_EXAMPLES.split('\n')
  102.         self.combo = ComboBoxEntrySave(const.TBP, cbes_defaults, title = _('Path Patterns'), edit_title = _('Edit saved patterns...'))
  103.         self.combo.show_all()
  104.         hbox.pack_start(self.combo, True, True, 0)
  105.         self.preview = qltk.Button(_('_Preview'), Gtk.STOCK_CONVERT)
  106.         self.preview.show()
  107.         hbox.pack_start(self.preview, False, True, 0)
  108.         self.pack_start(hbox, False, True, 0)
  109.         self.combo.get_child().connect('changed', self._changed)
  110.         model = ObjectStore()
  111.         self.view = Gtk.TreeView(model = model)
  112.         self.view.show()
  113.         sw = Gtk.ScrolledWindow()
  114.         sw.set_shadow_type(Gtk.ShadowType.IN)
  115.         sw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
  116.         sw.add(self.view)
  117.         self.pack_start(sw, True, True, 0)
  118.         vbox = Gtk.VBox()
  119.         addreplace = Gtk.ComboBoxText()
  120.         addreplace.append_text(_('Tags replace existing ones'))
  121.         addreplace.append_text(_('Tags are added to existing ones'))
  122.         addreplace.set_active(config.getboolean('tagsfrompath', 'add'))
  123.         addreplace.connect('changed', self._TagsFromPath__add_changed)
  124.         vbox.pack_start(addreplace, True, True, 0)
  125.         addreplace.show()
  126.         self.pack_start(vbox, False, True, 0)
  127.         filter_box = FilterPluginBox(self.handler, self.FILTERS)
  128.         filter_box.connect('preview', self._TagsFromPath__filter_preview)
  129.         filter_box.connect('changed', self._TagsFromPath__filter_changed)
  130.         self.filter_box = filter_box
  131.         self.pack_start(filter_box, False, True, 0)
  132.         self.save = Gtk.Button(stock = Gtk.STOCK_SAVE)
  133.         self.save.show()
  134.         bbox = Gtk.HButtonBox()
  135.         bbox.set_layout(Gtk.ButtonBoxStyle.END)
  136.         bbox.pack_start(self.save, True, True, 0)
  137.         self.pack_start(bbox, False, True, 0)
  138.         connect_obj(self.preview, 'clicked', self._TagsFromPath__preview, None)
  139.         connect_obj(parent, 'changed', self.__class__._TagsFromPath__preview, self)
  140.         connect_obj(self.save, 'clicked', self._TagsFromPath__save, addreplace, library)
  141.         for child in self.get_children():
  142.             child.show()
  143.         
  144.  
  145.     
  146.     def __filter_preview(self, *args):
  147.         Gtk.Button.clicked(self.preview)
  148.  
  149.     
  150.     def __filter_changed(self, *args):
  151.         self._changed(self.combo.get_child())
  152.  
  153.     
  154.     def _changed(self, entry):
  155.         self.save.set_sensitive(False)
  156.         self.preview.set_sensitive(bool(entry.get_text()))
  157.  
  158.     
  159.     def __add_changed(self, combo):
  160.         config.set('tagsfrompath', 'add', str(bool(combo.get_active())))
  161.  
  162.     
  163.     def __preview(self, songs):
  164.         if songs is None:
  165.             if not self.view.get_model():
  166.                 pass
  167.             songs = [ row[0].song for row in [] ]
  168.         if songs:
  169.             pattern_text = self.combo.get_child().get_text().decode('utf-8')
  170.         else:
  171.             pattern_text = ''
  172.         
  173.         try:
  174.             pattern = TagsFromPattern(pattern_text)
  175.         except re.error:
  176.             qltk.ErrorMessage(self, _('Invalid pattern'), _('The pattern\n\t<b>%s</b>\nis invalid. Possibly it contains the same tag twice or it has unbalanced brackets (< / >).') % util.escape(pattern_text)).run()
  177.             return None
  178.  
  179.         if pattern_text:
  180.             self.combo.prepend_text(pattern_text)
  181.             self.combo.write(const.TBP)
  182.         invalid = []
  183.         for header in pattern.headers:
  184.             if not min([ song.can_change(header) for song in songs ]):
  185.                 invalid.append(header)
  186.                 continue
  187.         if len(invalid) and songs:
  188.             if len(invalid) == 1:
  189.                 title = _('Invalid tag')
  190.                 msg = _('Invalid tag <b>%s</b>\n\nThe files currently selected do not support editing this tag.')
  191.             else:
  192.                 title = _('Invalid tags')
  193.                 msg = _('Invalid tags <b>%s</b>\n\nThe files currently selected do not support editing these tags.')
  194.             qltk.ErrorMessage(self, title, msg % ', '.join(invalid)).run()
  195.             pattern = TagsFromPattern('')
  196.         self.view.set_model(None)
  197.         model = ObjectStore()
  198.         for col in self.view.get_columns():
  199.             self.view.remove_column(col)
  200.         
  201.         render = Gtk.CellRendererText()
  202.         col = TreeViewColumn(_('File'), render)
  203.         col.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
  204.         
  205.         def cell_data_file(column, cell, model, iter_, data):
  206.             entry = model.get_value(iter_)
  207.             cell.set_property('text', entry.name)
  208.  
  209.         col.set_cell_data_func(render, cell_data_file)
  210.         
  211.         def cell_data_header(column, cell, model, iter_, header):
  212.             entry = model.get_value(iter_)
  213.             cell.set_property('text', entry.get_match(header))
  214.  
  215.         self.view.append_column(col)
  216.         for i, header in enumerate(pattern.headers):
  217.             render = Gtk.CellRendererText()
  218.             render.set_property('editable', True)
  219.             render.connect('edited', self._TagsFromPath__row_edited, model, header)
  220.             escaped_title = header.replace('_', '__')
  221.             col = Gtk.TreeViewColumn(escaped_title, render)
  222.             col.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
  223.             col.set_cell_data_func(render, cell_data_header, header)
  224.             self.view.append_column(col)
  225.         
  226.         for song in songs:
  227.             entry = ListEntry(song)
  228.             match = pattern.match(song)
  229.             for h in pattern.headers:
  230.                 text = match.get(h, '')
  231.                 for f in self.filter_box.filters:
  232.                     if f.active:
  233.                         text = f.filter(h, text)
  234.                         continue
  235.                 if not song.can_multiple_values(h):
  236.                     text = u', '.join(text.split('\n'))
  237.                 entry.matches[h] = text
  238.             
  239.             model.append([
  240.                 entry])
  241.         
  242.         if songs:
  243.             self.view.set_model(model)
  244.         self.preview.set_sensitive(False)
  245.         self.save.set_sensitive(len(pattern.headers) > 0)
  246.  
  247.     
  248.     def __save(self, addreplace, library):
  249.         pattern_text = self.combo.get_child().get_text().decode('utf-8')
  250.         pattern = TagsFromPattern(pattern_text)
  251.         model = self.view.get_model()
  252.         add = bool(addreplace.get_active())
  253.         win = WritingWindow(self, len(model))
  254.         win.show()
  255.         was_changed = set()
  256.         all_done = False
  257.         for entry in []:
  258.             song = entry.song
  259.             changed = False
  260.             if not song.valid():
  261.                 win.hide()
  262.                 dialog = OverwriteWarning(self, song)
  263.                 resp = dialog.run()
  264.                 win.show()
  265.                 if resp != OverwriteWarning.RESPONSE_SAVE:
  266.                     break
  267.                 
  268.             for i, h in enumerate(pattern.headers):
  269.                 text = entry.get_match(h)
  270.                 if text:
  271.                     can_multiple = song.can_multiple_values(h)
  272.                     if not add and h not in song or not can_multiple:
  273.                         song[h] = text
  274.                         changed = True
  275.                     else:
  276.                         for val in text.split('\n'):
  277.                             if val not in song.list(h):
  278.                                 song.add(h, val)
  279.                                 changed = True
  280.                                 continue
  281.                             continue
  282.                         if changed:
  283.                             
  284.                             try:
  285.                                 song.write()
  286.                             except:
  287.                                 util.print_exc()
  288.                                 WriteFailedError(self, song).run()
  289.                                 library.reload(song, changed = was_changed)
  290.                                 break
  291.  
  292.                             was_changed.add(song)
  293.                         if win.step():
  294.                             break
  295.                             continue
  296.                         all_done = True
  297.                         win.destroy()
  298.                         library.changed(was_changed)
  299.                         self.save.set_sensitive(not all_done)
  300.                         return None
  301.  
  302.     
  303.     def __row_edited(self, renderer, path, new, model, header):
  304.         entry = model[path][0]
  305.         new = new.decode('utf-8')
  306.         if entry.get_match(header) != new:
  307.             entry.replace_match(header, new)
  308.             self.preview.set_sensitive(True)
  309.             self.save.set_sensitive(True)
  310.  
  311.  
  312.